#include "ubrvm_orbit.h"
#include "DIVA_Manager.h"
#include "vmLibrary.h"

#define PLANE_SIZE 800.0f
#define COMPLEXITY 22
#define COLOR_MODULATE_PARAM_INDEX 1
// @@@@
/// constructor
//Name           : hyt
//Update Date    : 08/10/26
//Update History :
//				(1) VL_createEntity 必須給 meshname,material可給可不給,若想自行命名vm的開頭,則可以
//                   再加第三個參數 string specialhead
//              (2) VL_regBoudingBox 則需要 vm的entity 
//              (3) 由programmer自行決定node內容
//              (4) 若要在vm任何一個位置顯示文字,首先呼叫VL_createVMText(你想顯示的文字,文字node的開頭name)
//                  再來是呼叫VL_createTextNode(vm文字位置)
//              (5) 設定vm node顏色則呼叫VL_setEntityColor(vm entity , Vector4(colorvalue))來設定
ubrvm_orbit::ubrvm_orbit(xParameterPack xpp):ReferenceVM(xpp){
	int default_port_number = vmLibrary::instance().get_vm_default_input_parameters().size();
	assert(xpp.no == default_port_number+5);
	_pointedVM = xpp.paras[default_port_number+1].val_vm ;  // @@@@ this _pointedVM is actually a dummyVM
	_proxyVM = (dummyVM *) _pointedVM ; // @@@@ cast it to dummyVM to use the method  isPointedNULL()
	_shapeVM = xpp.paras[default_port_number+4].val_vm ; // this is the VM which is used to 
	_velocity = xpp.paras[default_port_number+2].val_int_ptr;
	_radius = xpp.paras[default_port_number+3].val_int_ptr;
	_head_node = NULL;
	_head_entity = NULL;
	_clicked = false;
	_created = false;
	_line_node = NULL;
	_myLine = NULL;
	VL_addVMAnimation();
	init_default_parameters();
}
ubrvm_orbit::~ubrvm_orbit(){
}
void ubrvm_orbit::load_3Dresources(){

	Ogre::Vector3 pos=_shapeVM->getPosition(); 
	Ogre::SceneNode *parent = _shapeVM->getParentSceneNode() ;
	Ogre::SceneNode *s = _shapeVM->getSceneNode();
	parent->removeChild(s);
	_SceneNode->addChild(s);
	_shapeVM->setParentSceneNode(_SceneNode);
	_shapeVM->setPosition(pos);

}
void ubrvm_orbit::reg_event_entity() {

	// register the relation of the entity and vm in diva manager
	// When this entity is clicked, mouse/keyboard VM will be passed to this VM

	// In this VM, we do not have entity here
}
void ubrvm_orbit::set_default_values() {

	_vm_rx_val = 0 ;
	_vm_ry_val = 0 ;
	_vm_rz_val = 0 ;

	Ogre::Vector3 sz = this->getActualSize();
	_vm_init_sizex = sz.x ;
	_vm_init_sizey = sz.y ;
	_vm_init_sizez = sz.z ;

	_vm_sizex_val = sz.x ;
	_vm_sizey_val = sz.y ;
	_vm_sizez_val = sz.z ;

	_vm_sizexscale_val = 1.0 ;
	_vm_sizeyscale_val = 1.0 ;
	_vm_sizezscale_val = 1.0 ;

	_vm_r_val = 0.3;  // white color but with transparency 0.1
	_vm_g_val = 0.3;
	_vm_b_val = 0.3;
	_vm_transparency_val = 1.0 ;

	_vm_yaw_val = 0 ;
	_vm_pitch_val = 0 ;
	_vm_roll_val = 0 ;

}
void ubrvm_orbit::init_private_attrs_started() {
	if(_radius != NULL){
		_radius_val = (*_radius);
	}
	if(_velocity != NULL){
		_velocity_val = (*_velocity);
	}
}
void ubrvm_orbit::init_color_and_transparency() {
	// we do not have entity in this VM
	// so we need to do nothing for color and transparency

}
void ubrvm_orbit::update_color_and_transparency() {
	init_color_and_transparency();
}
void ubrvm_orbit::VMValueUpdated() {
	_proxyVM->clearPointedVM();
	disableVMAnimation(); // we disable animation and wait for user to pick as a restart
}
void ubrvm_orbit::VMAnimation(const Ogre::FrameEvent & evt){
	if (_visible == false)  return ;
	if (_proxyVM->hasNULLvalue()) { // @@@@@
		return; ///假如pointedVM 是空的就直接return 不做下面的動作  因為在vmpicked那邊也沒new 出 ogrehead mesh 會造成錯誤
	}
	if(!_created){
		createOrbitNodeEntity();
		time(&t);
		_created = true;
	}

	time_t t1;

	time(&t1);

	if((t1 - t) > 10){
		disableVMAnimation();
		_head_node->detachAllObjects();
		_created = false;
		return;
	}

	// sine track? :)
	static double sines[4] ={_radius_val,_radius_val,-_radius_val,_radius_val};
	//static double sines[4] = {this->getPosition().x-50,this->getPosition().z-50,this->getPosition().x+50,this->getPosition().z+50};
	static const double adds[4] = {1.0,-1.0,1.0,1.0};

	for(int i=0;i<4;i++) {
		sines[i]+=adds[i]*evt.timeSinceLastFrame * _velocity_val;
	}
	Ogre::Real tx = ((sin(sines[0]) + sin(sines[1])) / 4 + 0.5 ) * (float)(COMPLEXITY-2) + 1 ;
	Ogre::Real ty = ((sin(sines[2]) + sin(sines[3])) / 4 + 0.5 ) * (float)(COMPLEXITY-2) + 1 ;

	Ogre::Real step = PLANE_SIZE / COMPLEXITY ;
	_head_node->resetToInitialState();
	_head_node->scale(1,1,1);
	Ogre::Vector3 newPos = Ogre::Vector3(step*tx-380, _pointedVM->getPosition().y, step*ty-380);
	Ogre::Vector3 diffPos = newPos - oldPos ;

	Ogre::Quaternion headRotation = Ogre::Vector3::UNIT_Z.getRotationTo(diffPos);
	oldPos = newPos ;
	_head_node->translate(newPos.x+_pointedVM->getPosition().x,newPos.y,newPos.z+_pointedVM->getPosition().z);
	_head_node->rotate(headRotation);

}
void ubrvm_orbit::VMSetVisible(bool vis) {
	if (_visible != vis) {
		  _visible = vis ;
        _SceneNode->setVisible(vis);
		_shapeVM->VMSetVisible(vis);
	}
}
void ubrvm_orbit::VMPicked(Ogre::Real x,Ogre::Real y,Ogre::Real z){
	enableVMAnimation();
	if (! _proxyVM->hasNULLvalue()) { //@@@@ 
		_shapeVM->setColorandTransparency(Ogre::Vector4(1.0,1.0,1.0, 1.0f));

		Ogre::Vector3 start = getWorldPosition() ;
		Ogre::Vector3 end = _proxyVM->getWorldPosition();
		oldPos = _pointedVM->getPosition();


	} else {  //@@@@
		// give the VM a black color
		_shapeVM->setColorandTransparency(Ogre::Vector4(0.6f, 0.2f, 0.2f, 1.0f));
		return; ///如過是空的就直接return 不去做下面 建出 ogrehead mesh
	}
	time_t t1;

	time(&t1);
	///預防使用者連點造成有好幾個 ogrehead

	if( t != NULL && t1 - t < 10){
		return;
	}
	time(&t);
}

/** we must override this method because this vm has no entity 
Its entity is at _shapeVM 
*/
bool ubrvm_orbit::isSubComponent(DIVA_VM *vm) {
	// if _shapevm is an entity vm, the test is straightforward
	// if _shapevm is a composite vm, the test is passed to the composite vm
	// to recurively check if it is a subcomponent
	return _shapeVM->isSubComponent(vm);
}
void ubrvm_orbit::scaleBodyToAbsSize(Ogre::Vector3 v){
	setBodyScale(Ogre::Vector3(v.x/_vm_init_sizex,
		v.y/_vm_init_sizey,
		v.z/_vm_init_sizez));
}
void ubrvm_orbit::setBodyScale(Ogre::Vector3 scale) {
	_SceneNode->setScale(scale);
}
bool ubrvm_orbit::isBodyScaleWrtSceneNode() { return true ; }

Ogre::Vector3 ubrvm_orbit::getOriginalBodySize() {
	return Ogre::Vector3(_vm_init_sizex, _vm_init_sizey, _vm_init_sizez) ;
}

Ogre::Vector3 ubrvm_orbit::getActualSize() {
	Ogre::Vector3 size=_shapeVM ->getActualSize();
	return size ;
}
Ogre::Vector3 ubrvm_orbit::getBodyScale() {
	return _SceneNode->getScale();
}

void ubrvm_orbit::createOrbitNodeEntity(){

	assert(_pointedVM !=NULL);
	
	oldPos = _pointedVM->getPosition();

	_head_node = _pointedVM->getSceneNode()->createChildSceneNode();
	_head_entity = DIVA_Manager::getInstance()->getSceneManager()->createEntity(getNewUniqueName(), "ogrehead.mesh");
	_head_node->attachObject(_head_entity);

	
	_parExp = DIVA_Manager::getInstance()->getSceneManager()->createParticleSystem(getNewUniqueName(),"Examples/PurpleFountain");

	_parExp->setVisible(true);
}